home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / prog / asm_n_z.arj / RECEIVE.ASM < prev    next >
Assembly Source File  |  1986-07-14  |  17KB  |  393 lines

  1.         Page    55,132
  2.         Title   SEND - Send a file using XMODEM protocol
  3.  
  4. SPECIAL Equ     0                       ;If true, include data size in block
  5.  
  6.         If      SPECIAL
  7. BLOCK   Struc
  8. B_SOH   Db      001H                    ;Start of header
  9. B_BLK1  Db      000H                    ;Block number
  10. B_BLK2  Db      0FFH                    ;(Block number)'
  11. B_CNT   Db      ?                       ;Count of bytes used in the data area
  12. B_DATA  Db      128 Dup (?)             ;The data area
  13. B_CHKSUM Db     ?                       ;Checksum of the data
  14. BLOCK   Ends
  15.         Else
  16. BLOCK   Struc
  17. B_SOH   Db      001H                    ;Start of header
  18. B_BLK1  Db      000H                    ;Block number
  19. B_BLK2  Db      0FFH                    ;(Block number)'
  20. B_DATA  Db      128 Dup (?)             ;The data area
  21. B_CHKSUM Db     ?                       ;Checksum of the data
  22. BLOCK   Ends
  23.         Endif
  24.  
  25. ERROR   Macro   N
  26.         Mov     AH,09H                  ;Display the error message
  27.         Lea     DX,ERRMSG&N             ;
  28.         Int     021H                    ;
  29.         Mov     AX,04C10H+N             ;And leave
  30.         Int     021H                    ;
  31.         Endm
  32.  
  33. CODE    Segment Public  'CODE'
  34. CODE    Ends
  35.  
  36. DATA    Segment Public  'DATA'
  37.  
  38. BAUD_TABLE Label Word
  39.         Dw      9600                    ;
  40.         Dw      4800                    ;
  41.         Dw      2400                    ;
  42.         Dw      1200                    ;
  43.         Dw      600                     ;
  44.         Dw      300                     ;
  45.         Dw      150                     ;
  46.         Dw      110                     ;
  47.  
  48. FILENAME Db     64 Dup (0)              ;Name of file to send
  49.  
  50. BUFFER  BLOCK   <>                      ;The block buffer
  51.  
  52. ERRMSG0 Db      '?No output file specified',13,10,'$'
  53. ERRMSG1 Db      '?Unable to create output file',13,10,'$'
  54. ERRMSG2 Db      '?Invalid baud rate specified',13,10,'$'
  55. ERRMSG3 Db      '?Transmitter time-out occurred',13,10,'$'
  56. ERRMSG4 Db      '?Error while writing the output file',13,10,'$'
  57. ERRMSG5 Db      '^C',13,10,'%Reception aborted via control-C',13,10,'$'
  58.  
  59. TXTMSG1 Db      'Waiting for transmitter...',13,10,'$'
  60. TXTMSG2 Db      'Block number '
  61. TXTNUM2 Db      '0    ',13,'$'
  62. TXTMSG3 Db      10,'Reception complete',13,10,'$'
  63. TXTMSG4 Db      'No retries needed',13,10,'$'
  64. TXTMSG5 Db      'Retry count was '
  65. TXTNUM5 Db      '0    ',13,10,'$'
  66.  
  67. MODE    Db      11101011B               ;9600 baud, odd parity, 1 stop bit,
  68.                                         ;8 bit character
  69.  
  70. BLOCK_COUNT Dw  0                       ;Total block count
  71. RETRY_COUNT Dw  0                       ;Retry count
  72.  
  73. BLK_NUM Db      001H                    ;8 bit block number expected.
  74.  
  75. DATA    Ends
  76.  
  77. STACK   Segment Stack   'STACK'
  78.  
  79.         Dw      128 Dup (?)             ;Program stack
  80.  
  81. STACK   Ends
  82.  
  83. CODE    Segment Public  'CODE'
  84.  
  85.         Assume  CS:CODE,DS:Nothing,ES:Nothing,SS:STACK
  86.  
  87. MAIN    Proc    Near
  88.         Sti                             ;Enable interrupts
  89.         Mov     AX,DATA                 ;Set up ES
  90.         Mov     ES,AX                   ;
  91.  
  92.         Assume  ES:DATA
  93.  
  94.         Cld                             ;Make sure the direction flag is clear
  95.         Mov     SI,080H                 ;Use SI to get the file name
  96.         Lodsb                           ;Get the length
  97.         Or      AL,AL                   ;Is there anything??
  98.         Jnz     MAIN01                  ;Yes. Proceed
  99. MAIN00: Mov     AX,ES                   ;Set up DS
  100.         Mov     DS,AX                   ;
  101.  
  102.         Assume  DS:DATA
  103.  
  104.         ERROR   0                       ;Nope. Die!
  105.  
  106.         Assume  DS:Nothing
  107.  
  108. MAIN01: Cbw                             ;Make it a word count
  109.         Mov     CX,AX                   ;Copy to CX
  110.  
  111. MAIN05: Jcxz    MAIN00                  ;If nothing left, error!
  112.         Dec     CX                      ;Decrement the character count
  113.         Lodsb                           ;And get the character
  114.         Cmp     AL,020H                 ;Space or less??
  115.         Ja      MAIN10                  ;Nope. Start the file name
  116.         Jmp Short MAIN05                ;Try again...
  117.  
  118. MAIN10: Lea     DI,FILENAME             ;Point DI to the file name buffer
  119. MAIN11: Stosb                           ;Store the character
  120.         Jcxz    MAIN20                  ;Got the file name. Open the file
  121.         Dec     CX                      ;Decrement the character count
  122.         Lodsb                           ;Get the next character
  123.         Cmp     AL,020H                 ;Is it a displayable character
  124.         Ja      MAIN11                  ;Yes. Put it in the file name
  125.  
  126. MAIN13: Jcxz    MAIN20                  ;No more characters?
  127.         Dec     CX                      ;Decrement the count
  128.         Lodsb                           ;Get another character
  129.         Cmp     AL,020H                 ;Space or less??
  130.         Ja      MAIN15                  ;Yes. See if it's a number
  131.         Jmp Short MAIN13                ;Keep looking
  132.  
  133. MAIN15: Xor     DX,DX                   ;Clear DX
  134. MAIN16: Cmp     AL,'0'                  ;Is this a digit??
  135.         Jae     MAIN18                  ;Yes.
  136. MAIN17: ERROR   2                       ;Not a valid baud rate
  137.  
  138. MAIN18: Cmp     AL,'9'                  ;Still a digit??
  139.         Ja      MAIN17                  ;Nope.
  140.         Sub     AL,'0'                  ;Convert to binary
  141.         Cbw                             ;Convert to a word
  142.         Shl     DX,1                    ;Double the previous number
  143.         Mov     BX,DX                   ;Save in BX for a bit
  144.         Shl     DX,1                    ;
  145.         Shl     DX,1                    ;
  146.         Add     DX,BX                   ;Now DX = (Old DX)*10
  147.         Add     DX,AX                   ;Add in the last digit
  148.         Jcxz    MAIN19                  ;All done.
  149.         Dec     CX                      ;Decrement the character count
  150.         Lodsb                           ;And get a character
  151.         Cmp     AL,020H                 ;Space or less?
  152.         Ja      MAIN16                  ;
  153.  
  154. MAIN19: Mov     AX,DX                   ;Put the baud rate in AX
  155.         Lea     DI,BAUD_TABLE           ;Point to the baud rate table
  156.         Mov     CX,8                    ;Eight entries in the table
  157.         Repne Scasw                     ;Look for this baud rate
  158.         Jne     MAIN17                  ;No good! Die!
  159.         Mov     AL,CL                   ;Get the index
  160.         Mov     CL,5                    ;And position it
  161.         Shl     AL,CL                   ;
  162.         Or      AL,00001011B            ;Odd parity, 1 stop bit, 8 bit character
  163.         Mov     MODE,AL                 ;And save it
  164.  
  165. MAIN20: Mov     AX,ES                   ;Set up DS
  166.         Mov     DS,AX                   ;
  167.  
  168.         Assume  DS:DATA
  169.  
  170.         Mov     AH,03CH                 ;Create the file specified
  171.         Xor     CX,CX                   ;With no attributes
  172.         Lea     DX,FILENAME             ;
  173.         Int     021H                    ;
  174.         Jnc     MAIN25                  ;Proceed!
  175.         ERROR   1                       ;Couldn't create the file
  176.  
  177. MAIN25: Mov     BX,AX                   ;Put the handle in BX
  178.  
  179.         Xor     AH,AH                   ;Initialize the RS232 channel
  180.         Mov     AL,MODE                 ;
  181.         Xor     DX,DX                   ;On channel zero
  182.         Int     014H                    ;
  183.  
  184.         Mov     AH,09H                  ;Display the "Waiting..." message
  185.         Lea     DX,TXTMSG1              ;
  186.         Int     021H                    ;
  187.  
  188.         Mov     CX,64                   ;This shall be our original timeout
  189. MAIN30: Mov     AH,06H                  ;See if a character is waiting
  190.         Mov     DL,0FFH                 ;
  191.         Int     021H                    ;
  192.         Jz      MAIN32                  ;Nope.
  193.         Cmp     AL,3                    ;Is it a control-C??
  194.         Jne     MAIN32                  ;
  195.  
  196.         Mov     AH,03EH                 ;Close the input file
  197.         Int     021H                    ;
  198.         ERROR   5                       ;And die
  199.  
  200. MAIN32: Mov     AX,0115H                ;Send a NAK to the transmitter
  201.         Xor     DX,DX                   ;(channel 0)
  202.         Int     014H                    ;
  203.  
  204.         Push    CX                      ;Save CX on the stack
  205.         Call    GET_BLOCK               ;Get a block of data
  206.         Pop     CX                      ;Restore CX
  207.         Jnc     MAIN35                  ;Got one. Go check it.
  208.  
  209. MAIN31: Loop    MAIN30                  ;Repeat until CX = 0
  210.         Mov     AH,03EH                 ;Close the input file
  211.         Int     021H                    ;
  212.         ERROR   3                       ;And die!
  213.  
  214. MAIN35: Cmp     BUFFER.B_SOH,04H        ;Is this the end of the file??
  215.         Je      MAIN80                  ;Yes. Close the file and leave
  216.  
  217.         Lea     DI,TXTNUM2              ;Fill in the block number
  218.         Mov     AX,BLOCK_COUNT          ;
  219.         Call    FILL_NUM                ;
  220.         Mov     AH,09H                  ;Display the block number
  221.         Lea     DX,TXTMSG2              ;
  222.         Int     021H                    ;
  223.  
  224.         Mov     AH,040H                 ;Write the file...
  225.         If      SPECIAL
  226.         Mov     CL,BUFFER.B_CNT         ;This many bytes only!
  227.         Xor     CH,CH                   ;
  228.         Else
  229.         Mov     CX,128                  ;Up to 128 bytes
  230.         Endif
  231.         Lea     DX,BUFFER.B_DATA        ;From our buffer
  232.         Int     021H                    ;
  233.         Jnc     MAIN40                  ;Got it; now ship it
  234.         Mov     AH,03EH                 ;Close the input file
  235.         Int     021H                    ;
  236.         ERROR   4                       ;And die (for some unknown reason)
  237.  
  238. MAIN40: Mov     AX,0105H                ;Send an ACK
  239.         Xor     DX,DX                   ;
  240.         Int     014H                    ;
  241.  
  242. MAIN42: Call    GET_BLOCK               ;Get another block
  243.         Jnc     MAIN35                  ;Check for EOF.
  244.  
  245.         Mov     AX,0115H                ;Send another NAK (just in case)
  246.         Xor     DX,DX                   ;
  247.         Int     014H                    ;
  248.         Jmp Short MAIN42                ;And try again
  249.  
  250. ;
  251. ;       End of file...
  252. ;
  253.  
  254. MAIN80: Mov     AX,0105H                ;Send a final ACK
  255.         Xor     DX,DX                   ;
  256.         Int     014H                    ;
  257.  
  258.         Mov     AH,09H                  ;Display the EOT message
  259.         Lea     DX,TXTMSG3              ;
  260.         Int     021H                    ;
  261.  
  262.         Mov     AH,03EH                 ;Close the input file
  263.         Int     021H                    ;
  264.  
  265.         Cmp     RETRY_COUNT,0           ;Did we have to do any retries??
  266.  
  267.         Mov     AH,09H                  ;No retries needed
  268.         Lea     DX,TXTMSG4              ;
  269.         Int     021H                    ;
  270.         Jmp Short MAIN99                ;Leave
  271.  
  272. MAIN95: Lea     DI,TXTNUM5              ;Point to the buffer
  273.         Mov     AX,RETRY_COUNT          ;Get the count
  274.         Call    FILL_NUM                ;
  275.         Mov     AH,09H                  ;And display the message
  276.         Lea     DX,TXTMSG5              ;
  277.         Int     021H                    ;
  278.  
  279. MAIN99: Mov     AX,04C00H               ;And leave
  280.         Int     021H                    ;
  281. MAIN    Endp
  282.  
  283. ;
  284. ;
  285. ;
  286.  
  287. FILL_NUM Proc   Near
  288.         Xor     CX,CX                   ;Clear the character count
  289.         Mov     SI,10                   ;Use SI to divide with
  290. FILL10: Xor     DX,DX                   ;
  291.         Div     SI                      ;Divide DX:AX by SI (10)
  292.         Add     DL,'0'                  ;Convert DL to ASCII
  293.         Push    DX                      ;Save it on the stack
  294.         Inc     CX                      ;Increment the character count
  295.         Or      AX,AX                   ;Any more to do??
  296.         Jnz     FILL10                  ;Yes. Keep going
  297.         Cld                             ;(just to be sure)
  298. FILL20: Pop     AX                      ;Get a character from the stack
  299.         Stosb                           ;And store it
  300.         Loop    FILL20                  ;Repeat CX times
  301.         Ret                             ;And return
  302. FILL_NUM Endp
  303.  
  304. ;
  305. ;       Get a block from the transmitter
  306. ;
  307.  
  308. GET_BLOCK Proc  Near
  309.         Cld                             ;(just to be sure)
  310.         Lea     DI,BUFFER               ;Point to the buffer
  311.         Mov     CX,20                   ;Time out for the first byte
  312.  
  313. GETB10: Mov     AH,06H                  ;See if a character is waiting
  314.         Mov     DL,0FFH                 ;
  315.         Int     021H                    ;
  316.         Jz      GETB12                  ;Nope.
  317.         Cmp     AL,3                    ;Is it a control-C??
  318.         Jne     GETB12                  ;
  319.  
  320.         Mov     AH,03EH                 ;Close the input file
  321.         Int     021H                    ;
  322.         ERROR   5                       ;And die
  323.  
  324. GETB12: Mov     AH,02H                  ;Get a character
  325.         Xor     DX,DX                   ;
  326.         Int     014H                    ;
  327.         Test    AH,08EH                 ;Any errors??
  328.         Jnz     GETB14                  ;Yup. Ignore it!
  329.         Cmp     AL,01H                  ;SOH??
  330.         Je      GETB20                  ;Yes. Start the block
  331.         Cmp     AL,04H                  ;End-of-text??
  332.         Je      GETB15                  ;Yes. Return it.
  333.         Jmp Short GETB12                ;Wait for another character
  334.  
  335. GETB14: Loop    GETB10                  ;Repeat until CX = 0
  336.         Stc                             ;Set the carry
  337.         Ret                             ;And return
  338.  
  339. GETB15: Stosb                           ;Store the EOT
  340.         Clc                             ;Clear carry...
  341.         Ret                             ;...and return
  342.  
  343. GETB20: Mov     CX,(Size BLOCK-1)       ;Repeat for the entire block
  344.         Stosb                           ;Store the SOH
  345. GETB22: Mov     SI,4                    ;Use SI for a timeout count
  346. GETB24: Mov     AH,02H                  ;Wait for another character
  347.         Xor     DX,DX                   ;
  348.         Int     014H                    ;
  349.         Test    AH,080H                 ;Time-out??
  350.         Jz      GETB26                  ;Nope.
  351.         Dec     SI                      ;Decrement the time-out count
  352.         Jnz     GETB24                  ;And try again
  353.         Jmp     SEND_RETRY              ;Send a retry
  354.  
  355. GETB26: Stosb                           ;Store the character
  356.         Loop    GETB22                  ;And try again
  357.  
  358.         Mov     AL,BLK_NUM              ;Get the expected block number
  359.         Cmp     AL,BUFFER.B_BLK1        ;Is this it??
  360.         Jne     SEND_RETRY              ;Nope.
  361.         Xor     AL,0FFH                 ;Complement AL
  362.         Cmp     AL,BUFFER.B_BLK2        ;Double check
  363.         Jne     SEND_RETRY              ;Nope.
  364.  
  365.         Lea     SI,BUFFER.B_DATA        ;Compute the checksum
  366.         Xor     AH,AH                   ;Clear AH
  367.         Xor     DX,DX                   ;Keep the checksum in DX
  368.         Mov     CX,128                  ;Repeat for 128 bytes
  369. GETB30: Lodsb                           ;Get a byte
  370.         Add     DX,AX                   ;Add it to DX
  371.         Loop    GETB30                  ;And repeat
  372.         Mov     AX,DX                   ;Put the sum in AX
  373.         Mov     DL,255                  ;Now divide by 255
  374.         Div     DL                      ;
  375.         Cmp     BUFFER.B_CHKSUM,AH      ;See if the check sum is O.K.
  376.         Jne     SEND_RETRY              ;Nope. Send a retry
  377.  
  378.         Inc     BLK_NUM                 ;Increment the expected block number
  379.         Inc     BLOCK_COUNT             ;And the block count
  380.         Clc                             ;
  381.         Ret                             ;Otherwise return with carry clear
  382.  
  383. SEND_RETRY:
  384.         Mov     AX,0115H                ;Send a NAK
  385.         Xor     DX,DX                   ;
  386.         Int     014H                    ;
  387.         Inc     RETRY_COUNT             ;Increment the retry count
  388.         Jmp     GET_BLOCK               ;And try all over again
  389. GET_BLOCK Endp
  390.  
  391. CODE    Ends
  392.         End     MAIN